import { Component, ViewChild, AfterViewInit, forwardRef, Input, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { DateTimeHelper } from '@shared/helpers/DateTimeHelper';
import { DateTime } from 'luxon';
import { FlatpickrOptions } from 'ng2-flatpickr';
import { runInThisContext } from 'vm';
import { DateTimeService } from '../timing/date-time.service';

declare var require: any;

if(typeof window !== 'undefined'){
    const flatpickr = require( 'flatpickr' );
    const Zh = require("flatpickr/dist/l10n/zh.js").default.zh;
    flatpickr.default.localize(Zh); // 默认语言环境现在是中文
}

@Component({
	selector: 'flatpickr-ext',
	template: `
		<div class="ng2-flatpickr-input-container" #flatpickr >
			<input *ngIf="!hideButton" [disabled]="disableDate" name="{{ctlName}}" class="ng2-flatpickr-input {{ addClass }}" [placeholder]="placeholder" [tabindex]="tabindex" type="text" (focus)="onFocus($event)"  data-input>
			<ng-content></ng-content>
		</div>
		`,
	providers: [
		{
			provide: NG_VALUE_ACCESSOR,
			useExisting: forwardRef( () => FlatpickrExtComponent ),
			multi: true
		}
	]
})
export class FlatpickrExtComponent implements AfterViewInit, ControlValueAccessor, OnChanges {

  	public flatpickr: Object;
  	private _tabindex = 0;
	onTouchedFn: Function = () => { };

	private defaultFlatpickrOptions: FlatpickrOptions = {
		wrap: true,
		clickOpens: true,
		time_24hr: true,
        enableTime: true,
		onChange: ( selectedDates: any ) => { this.writeValue( selectedDates ); },
        dateFormat:'Y/m/d H:i'
	};

	@ViewChild('flatpickr', {
		static: true
	})
	flatpickrElement: any;

	@Input()
	config: FlatpickrOptions;

	@Input()
	placeholder: string = "";

 	@Input()
	addClass: string = "";

    @Input()
    ctlName:string

	@Input()
	get tabindex() { return this._tabindex; }
	set tabindex( ti: number ) { this._tabindex = Number( ti ); }

	@Input()
	hideButton = false;

    @Input() disableDate:boolean ;

    @Input() date:DateTime;

    @Output() dateChange = new EventEmitter<DateTime>();

    @Input() uTime:string;
    @Output() uTimeChange = new EventEmitter<string>();

    @Input() timetype:string;  // dateTime , number

	///////////////////////////////////
    originDate:number;

    constructor(private _dateTimeService:DateTimeService){

    }

	writeValue( value:any ) {
		this.propagateChange( value );
	}

	registerOnChange( fn: any ) {
		this.propagateChange = fn;
	}

	registerOnTouched(fn: any): void {
		this.onTouchedFn = fn;
	}

	propagateChange = ( value: any ) => {
        
        if (!value || value.length == 0){
            if (!this.originDate) return;
            this.originDate = 0;
            this.updateTimeBack();
            return;
        }
        if (value.length == 1){
            let item = value[0];
            if (this.originDate){
                if (this.originDate == item.getTime()){
                    return
                }
            }
            this.originDate = item.getTime();
            this.updateTimeBack(item);
        }
        
    };

	///////////////////////////////////

	setDateFromInput( date: any ) {
		this.flatpickrElement.nativeElement._flatpickr.setDate( date, true );
	}

	setAltInputPlaceholder( placeholder: string ) {
		this.flatpickrElement.nativeElement._flatpickr.altInput.setAttribute( 'placeholder', placeholder );
	}

	ngAfterViewInit() {
		if( this.config ) {
			Object.assign( this.defaultFlatpickrOptions, this.config );
		}
		if( this.flatpickrElement.nativeElement.flatpickr ) {
			this.flatpickr = this.flatpickrElement.nativeElement.flatpickr( this.defaultFlatpickrOptions );
		}

	}

	ngOnChanges( changes: SimpleChanges ) {

		setTimeout(() => {
			if( this.flatpickrElement.nativeElement 
				&& this.flatpickrElement.nativeElement._flatpickr) {
					
					if( this.config?.altInput
						&& changes.hasOwnProperty( 'placeholder' ) 
						&& changes[ 'placeholder' ].currentValue ) {
							this.setAltInputPlaceholder( changes[ 'placeholder' ].currentValue );
						}
	
					if (changes.hasOwnProperty('uTime') || changes.hasOwnProperty('date')){
						
						if (this.timetype && this.timetype == 'number'){
							let _dateTime:DateTime;
							if (this.uTime){
								let date = new Date(Number(this.uTime));
								_dateTime = DateTime.fromJSDate(date);
							}
							else _dateTime = null
							let newDate = _dateTime ? _dateTime.toJSDate() : null;
							this.setDateFromInput(newDate);
						}
						else { 
							let _dateTime:DateTime;
							if (this.date){
								_dateTime = this.date
							}
							else _dateTime = null
							let newDate = _dateTime ? _dateTime.toJSDate() : null;
							this.setDateFromInput(newDate);
						}
					}
				 
				}
		}, 0);
		
	}
    
    private updateTimeBack(dateInput?:Date){ 
        if (this.timetype && this.timetype == 'number'){
            if (!dateInput){
                this.uTime = '';
                this.uTimeChange.emit('');
                return;
            }
			let newTime = dateInput.getTime().toString();
            this.uTime = newTime;
            this.uTimeChange.emit(newTime);
        }
        else{
            if (!dateInput){
                this.date = null;
                this.dateChange.emit(null);
                return;
            }
            let newTime = this._dateTimeService.fromJSDate(dateInput)
            this.date = newTime;
            this.dateChange.emit(newTime);
 
        }
    }
	
	onFocus(event: any) {
		this.onTouchedFn();
	}
}